﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Ink;
using System.Windows.Input;


namespace ESJImporter
{
    /// <summary>
    /// a class structure for containing the edge journal
    /// </summary>
    public class ESJournal
    {
        public XElement esjxmldoc;             // the currently loaded ESJ document
        public ArrayList edgejournalpages;     // the pages of the currently loaded ESJ

        #region constructors
        private void init()
        {
            edgejournalpages = new ArrayList();
            //esjxmldoc = new XDocument();
        }

        public ESJournal()
        {
            init();
        }

        /// <summary>
        /// constructor taking a esj or xml file as input
        /// </summary>
        /// <param name="filename"></param>
        public ESJournal(string filename)
        {
            init();
            loadfile(filename);
        }

        #endregion constructors

        /// <summary>
        /// load a file into the journal class
        /// </summary>
        /// <param name="filename"></param>
        public void loadfile(string filename)
        {
            // load document into esjxmldoc
            esjxmldoc = new XElement("root");

            FileInfo fiInFile = new FileInfo(filename);
            Stream s = new FileStream(filename, FileMode.Open);
            switch (fiInFile.Extension.ToLower())
            {
                case ".xml":
                    // XML File
                    XmlTextReader xr = new XmlTextReader(s);
                    esjxmldoc = XElement.Load(xr);
                    xr.Close();
                    break;
                case ".esj":
                    // zipped XML (esj)
                    System.IO.Compression.GZipStream gzs = new System.IO.Compression.GZipStream(s, System.IO.Compression.CompressionMode.Decompress, true);
                    XmlTextReader xr2 = new XmlTextReader(gzs);
                    esjxmldoc = XElement.Load(xr2);
                    gzs.Close();
                    break;
                default:
                    // unknown file format
                    throw new Exception("unknown file format");
            }
            s.Close();

            // read the pages from the file and store
            IEnumerable<XNode> esjXMLPages = from pages in esjxmldoc.Descendants("page") select (XNode)pages;
            foreach (XElement XMLPage in esjXMLPages)
            {
                // create page class and add to array
                ESJournalPage esjpage = new ESJournalPage(XMLPage);
                edgejournalpages.Add(esjpage);
            }

        }

        /// <summary>
        /// get the xml of a specific page in the journal
        /// </summary>
        /// <param name="pageid"></param>
        /// <returns></returns>
        public ESJournalPage getpage(string pageid)
        {
            foreach (ESJournalPage page in edgejournalpages)
            {
                if (pageid == page.pagename) return page;
            }
            return null;
        }
    }

    /// <summary>
    /// the class structure for a single Edge Journal page
    /// </summary>
    public class ESJournalPage
    {
        public ArrayList pagestrokes;    // the strokes of the page
        public XElement pagecontent;    // the (XML) content of the page
        public string pagename;         // a unique identifier of the page
        public string tabname;          // the name of the tab the page belongs to

        private void init()
        {
            pagestrokes = new ArrayList();
            pagename = Guid.NewGuid().ToString();
            tabname = "";
        }

        public ESJournalPage()
        {
            init();
        }

        public ESJournalPage(XElement content)
        {
            init();

            pagecontent = content;

            // read tabname
            tabname = content.Attribute("tabname").Value;

            // read strokes from the page
            IEnumerable<XNode> XMLStrokes = from strokes in content.Descendants("stroke") select (XNode)strokes;

            int strokecounter = 1;
            foreach (XElement XMLStroke in XMLStrokes)
            {
                string strokeguid = Guid.NewGuid().ToString();
                pagestrokes.Add(XMLStroke);

                strokecounter++;
            }
        }
    }

    /// <summary>
    /// a helper class (library) for conversion routines
    /// provide this function for any other input file => extend the interoperability scope
    /// </summary>
    class EdgeJournalFunctions
    {
        /// <summary>
        /// Convert the page xml into a stroke collection
        /// todo: could be part of ESJournalPage
        /// </summary>
        /// <param name="pagenode"></param>
        /// <returns></returns>
        static public StrokeCollection createStrokeCollectionFromPage(ESJournalPage esjpage, Preferences settings)
        {
            StrokeCollection esjstrokes = new StrokeCollection();

            double minx = 999;
            double miny = 999;
            double maxx = 0;
            double maxy = 0;
            double zoom = settings.ZoomFactor;
            if (settings.getDeviceType() == "EE") 
                zoom = zoom * 0.6;    // check

            foreach (XElement strokedata in esjpage.pagestrokes)
            {
                StylusPointCollection esjspc = new StylusPointCollection();

                char[] seps = { ' ' };
                string[] strvalues = strokedata.Value.Split(seps);
                for (int i = 0; i < strvalues.Length - 1; i += 2)
                {
                    double xps = zoom * float.Parse(strvalues[i]);
                    double yps = zoom * float.Parse(strvalues[i + 1]);
                    esjspc.Add(new StylusPoint(xps, yps));
                    minx = Math.Min(xps, minx);
                    miny = Math.Min(yps, miny);
                    maxx = Math.Max(xps, maxx);
                    maxy = Math.Max(yps, maxy);
                }

                DrawingAttributes das = new DrawingAttributes();
                // get color
                string esjcolor = strokedata.Attribute("color").Value;
                System.Drawing.Color col = settings.getColor(esjcolor);
                das.Color = System.Windows.Media.Color.FromArgb(col.A, col.R, col.G, col.B);

                // get width of stroke
                string esjwidth = strokedata.Attribute("width").Value;
                das.Width = settings.getWidth(esjwidth);

                esjstrokes.Add(new Stroke(esjspc, das));
            }
            return esjstrokes;
        }

    }
}
